//
// Created by cnsunrun on 2018/3/26.
//


#include <jni.h>
#include <string.h>
#include "app-base64.h"

/**
 * native层非对称加密实现- 加密方法,使用的仍然为java中的PKCS8EncodedKeySpec类进行的加密,
 * @param env
 * @param content_  待加签名的字符串
 * @return rsa2签名后的字符串
 */
jstring RSA2SIGN(JNIEnv *env, jstring content_) {
    const char *string = RSA_PRIVATE_KEY;
    const char *content = jstringTochars(env, content_);//env->GetStringUTFChars(content_, 0);//

    //获取需要使用的java类
    jclass base64_cls = env->FindClass("android/util/Base64");
    jclass pkcs8_cls = env->FindClass("java/security/spec/PKCS8EncodedKeySpec");
    jclass keyfactory_cls = env->FindClass("java/security/KeyFactory");
    jclass signature_cls = env->FindClass("java/security/Signature");

    jmethodID base64_decode_mtd = env->GetStaticMethodID(base64_cls, "decode",
                                                         "(Ljava/lang/String;I)[B");
    jbyteArray rsa_key_byte = (jbyteArray) env->CallStaticObjectMethod(base64_cls,
                                                                       base64_decode_mtd,
                                                                       charsToJstring(env, string),
                                                                       0);
    jmethodID pkcs8_init_mtd = env->GetMethodID(pkcs8_cls, "<init>", "([B)V");
    jobject pkcs8_obj = env->NewObject(pkcs8_cls, pkcs8_init_mtd, rsa_key_byte);

    jmethodID keyfactory_init_mtd = env->GetStaticMethodID(keyfactory_cls, "getInstance",
                                                           "(Ljava/lang/String;)Ljava/security/KeyFactory;");
    jstring RSA = env->NewStringUTF("RSA");
    jobject keyfactory_obj = env->CallStaticObjectMethod(keyfactory_cls, keyfactory_init_mtd, RSA);

    jmethodID generatePrivate_mtd = env->GetMethodID(keyfactory_cls, "generatePrivate",
                                                     "(Ljava/security/spec/KeySpec;)Ljava/security/PrivateKey;");

    jobject privateKey = env->CallObjectMethod(keyfactory_obj, generatePrivate_mtd, pkcs8_obj);

    jmethodID signature_init_mtd = env->GetStaticMethodID(signature_cls, "getInstance",
                                                          "(Ljava/lang/String;)Ljava/security/Signature;");
    jstring SHA256WithRSA = env->NewStringUTF("SHA256WithRSA");
    jobject signature_obj = env->CallStaticObjectMethod(signature_cls, signature_init_mtd,
                                                        SHA256WithRSA);

    jmethodID signature_init_sign_mtd = env->GetMethodID(signature_cls, "initSign",
                                                         "(Ljava/security/PrivateKey;)V");
    env->CallVoidMethod(signature_obj, signature_init_sign_mtd, privateKey);

    jmethodID signature_update_mtd = env->GetMethodID(signature_cls, "update",
                                                      "([B)V");
    env->CallVoidMethod(signature_obj, signature_update_mtd, convert_char(env, (char *) content));

    jmethodID signature_sign_mtd = env->GetMethodID(signature_cls, "sign",
                                                    "()[B");
    jbyteArray result = (jbyteArray) env->CallObjectMethod(signature_obj, signature_sign_mtd);

    jmethodID base64_encodeToString_mtd = env->GetStaticMethodID(base64_cls, "encodeToString",
                                                                 "([BI)Ljava/lang/String;");
    jstring resultStr = (jstring) env->CallStaticObjectMethod(base64_cls, base64_encodeToString_mtd,
                                                              result, 0);
    //释放出从java端接收的字符串
    env->ReleaseStringUTFChars(content_, string);
    return resultStr;
}
